home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Utilities / Installers / Smaller Installer 2.0.1 / Preinstalled version / Examples / Hook Procedure Examples / AliasAndDeleteHook / AliasAndDeleteHook.c next >
Encoding:
C/C++ Source or Header  |  1996-07-26  |  12.7 KB  |  420 lines  |  [TEXT/CWIE]

  1. /******************************************************************************
  2.     Smaller Installer © 1996 Bill Goodman, All Rights Reserved
  3. *******************************************************************************
  4.  
  5. Alias and Delete Hook Example
  6.  
  7. This installer hook procedure creates aliases and deletes files. During
  8. installation, any file or folder whose name ends with "^A", "^D" or "^S" will
  9. have an alias created for it in the Apple Menu Items, Desktop or Startup folder
  10. respectively. Any file or folder whose name ends with "^X" will be deleted (no
  11. file will be installed in its place).
  12.  
  13. To build this hook procedure, compile this code and create a code resource
  14. (Type:SICR, ID:501, non-preloaded, nonpurgeable, unlocked, unprotected,
  15. non-sysheap). Add this resource to the "AliasAndDeleteHook.rsrc" file. Copy all
  16. the resources in "AliasAndDeleteHook.rsrc" to your installer's resource file.
  17.  
  18. ******************************************************************************/
  19.  
  20. // This file is compatible with version 2.1 of the universal headers
  21. #include <Aliases.h>
  22. #include <Dialogs.h>
  23. #include <Finder.h>
  24. #include <Folders.h>
  25. #include <GestaltEqu.h>
  26. #include <Resources.h>
  27. #include <TextUtils.h>
  28.  
  29. #ifdef __MWERKS__
  30. #include <A4Stuff.h>
  31. #endif
  32.  
  33. #ifdef THINK_C
  34. #include <SetUpA4.h>
  35. #endif
  36.  
  37. #include "SIHookProc.h"
  38.  
  39.  
  40. /******************************************************************************
  41.     Function Prototypes
  42. ******************************************************************************/
  43. void AfterItemFunction(void);
  44. void BeforeItemFunction(void);
  45. OSErr DeleteItem(short delVRefNum, long delDirID, StringPtr delName);
  46.  
  47.  
  48. /******************************************************************************
  49.     Constant Definitions
  50. ******************************************************************************/
  51. // Alert Definitions
  52. #define aliasAlrt        500    // "An error occurred while creating an alias. Please remove all installed items and try again."
  53. #define deleteAlrt    501    // "Unable to remove “^0”. Please remove this item and try again."
  54.  
  55.  
  56. /******************************************************************************
  57.     Variable Definitions
  58. ******************************************************************************/
  59. SIHookParmBlk *gParms;                    // Global pointer to parameter block
  60. unsigned char gEmptyStr[] = "\p";    // Global empty string
  61.  
  62.  
  63. /*****************************************************************************/
  64. pascal void main(
  65.         SIHookParmBlk *parmBlk    // Pointer to parameter block
  66.         )
  67. /******************************************************************************
  68.     This is the main entry point for the installer hook procedure.
  69. ******************************************************************************/
  70. {
  71. #ifdef __MWERKS__
  72. long holdA4;
  73. #endif
  74.  
  75. // Set up access to global variables
  76. #ifdef THINK_C
  77. RememberA0();
  78. SetUpA4();
  79. #endif
  80.  
  81. #ifdef __MWERKS__
  82. holdA4 = SetCurrentA4();
  83. #endif
  84.  
  85. gParms = parmBlk;
  86.  
  87. switch (gParms->function)
  88.     {
  89.     case siHookBeforeItem:
  90.         BeforeItemFunction();
  91.         break;
  92.  
  93.     case siHookAfterItem:
  94.         AfterItemFunction();
  95.         break;
  96.     }
  97.  
  98. // Restore original A4 value
  99. #ifdef THINK_C
  100. RestoreA4();
  101. #endif
  102.  
  103. #ifdef __MWERKS__
  104. SetA4(holdA4);
  105. #endif
  106. }
  107.  
  108.  
  109. /*****************************************************************************/
  110. void BeforeItemFunction(void)
  111. /******************************************************************************
  112.     Input parameters:
  113.         "targetVRefNum"    Volume reference number of target volume
  114.         "groupAPFlags"        Groups currently selected
  115.         "groupQUSel"
  116.         "groupVZSel"
  117.         "group32Flags"
  118.         "group64Flags"
  119.         "group96Flags"
  120.         "groupEnvironFlags"
  121.         "filesRemaining"    Number of files remaining to install or remove
  122.         "bytesRemaining"    Number of bytes of data remaining to install or remove
  123.         "doingRemove"        Non-zero if doing remove operation
  124.         "anyItemsSkipped"    Non-zero if any item has been skipped during operation
  125.         "desVRefNum"        Volume reference number of destination volume
  126.         "desDirID"            Directory ID of destination directory
  127.         "itemName"            Name of item to install or remove
  128.         "itemIsFolder"        Non-zero if item is a folder
  129.         "fileType"            File type (files only)
  130.         "fileCreator"        File creator (files only)
  131.         "createDate"        Creation date (files only)
  132.         "lastModDate"        Last modification date (files only)
  133.         "rsrcForkLen"        Length of resource fork (files only)
  134.         "dataForkLen"        Length of data fork (files only)
  135.  
  136.     Returns:
  137.         "result"                Hook result code (siHookNoErr, siHookQuit, siHookAbort, siHookSkip, siHookItemDone)
  138.         "desDirID"            Directory ID of destination directory
  139.         "itemName"            Name of item to install or remove
  140.         "itemInfo"            Reference passed to AfterItem call
  141.  
  142.     This function is called before each item is installed or removed.
  143. ******************************************************************************/
  144. {
  145. short length;
  146. unsigned char tag;
  147.  
  148. gParms->itemInfo = 0;    // Clear tag info
  149.  
  150. // Check item name to see if tag is present
  151. length = gParms->itemName[0];
  152. if (length > 2)
  153.     {
  154.     if (gParms->itemName[length - 1] == '^')
  155.         {
  156.         tag = gParms->itemName[length];
  157.         if ((tag == 'A') || (tag == 'D') || (tag == 'S'))
  158.             {    // Item has alias tag
  159.             gParms->itemInfo = tag;        // Pass tag to AfterItem hook
  160.             gParms->itemName[0] -= 2;    // Remove tag so overwrite, create and remove use standard name
  161.             return;
  162.             }
  163.         if (tag == 'X')
  164.             {    // Item has delete tag
  165.             if (!gParms->doingRemove)
  166.                 {    // Only do delete if performing "install" operation
  167.                 gParms->itemName[0] -= 2;    // Remove tag
  168.                 if (DeleteItem(gParms->desVRefNum, gParms->desDirID, gParms->itemName))
  169.                     {    // Item could not be deleted
  170.                     ParamText(gParms->itemName, gEmptyStr, gEmptyStr, gEmptyStr);
  171.                     StopAlert(deleteAlrt, NULL);
  172.                     gParms->result = siHookQuit;    // Force installer to quit
  173.                     return;
  174.                     }
  175.                 }
  176.             gParms->result = siHookItemDone;    // Tell installer item has been handled
  177.             return;
  178.             }
  179.         }
  180.     }
  181. }
  182.  
  183.  
  184. /*****************************************************************************/
  185. void AfterItemFunction(void)
  186. /******************************************************************************
  187.     Input parameters:
  188.         "targetVRefNum"    Volume reference number of target volume
  189.         "groupAPFlags"        Groups currently selected
  190.         "groupQUSel"
  191.         "groupVZSel"
  192.         "group32Flags"
  193.         "group64Flags"
  194.         "group96Flags"
  195.         "groupEnvironFlags"
  196.         "filesRemaining"    Number of files remaining to install or remove
  197.         "bytesRemaining"    Number of bytes of data remaining to install or remove
  198.         "doingRemove"        Non-zero if doing remove operation
  199.         "anyItemsSkipped"    Non-zero if any item has been skipped during operation
  200.         "itemWasSkipped"    Non-zero if this item was skipped
  201.         "desVRefNum"        Volume reference number of destination volume
  202.         "desDirID"            Directory ID of destination directory
  203.         "itemName"            Name of item that was installed or removed
  204.         "itemIsFolder"        Non-zero if item is a folder
  205.         "fileType"            File type (files only)
  206.         "fileCreator"        File creator (files only)
  207.         "createDate"        Creation date (files only)
  208.         "lastModDate"        Last modification date (files only)
  209.         "rsrcForkLen"        Length of resource fork (files only)
  210.         "dataForkLen"        Length of data fork (files only)
  211.         "itemInfo"            Reference passed from BeforeItem call
  212.  
  213.     Returns:
  214.         "result"                Hook result code (siHookNoErr, siHookQuit, siHookAbort)
  215.  
  216.     This function is called after each item is installed or removed.
  217. ******************************************************************************/
  218. {
  219. OSErr error;
  220. long feature;
  221. OSType folderType;
  222. Boolean fileCreated = false;
  223. Boolean fileOpen = false;
  224. short aliasVRefNum;
  225. long aliasDirID;
  226. short aliasResFileNum;
  227. OSType aliasType;
  228. OSType aliasCreator;
  229. AliasHandle aliasHdl;
  230. FSSpec targFSS;
  231. FInfo finderInfo;
  232. CInfoPBRec ib;
  233.  
  234. if (!gParms->itemInfo)
  235.     return;    // No action required unless file was tagged
  236.  
  237. // No action required if not running System 7.0 or higher
  238. if (Gestalt(gestaltSystemVersion, &feature))
  239.     return;
  240. if (feature < 0x0700)
  241.     return;
  242.  
  243. // Get VRefNum and DirID for alias
  244. if (gParms->itemInfo == 'A')
  245.     folderType = kAppleMenuFolderType;
  246. else if (gParms->itemInfo == 'S')
  247.     folderType = kStartupFolderType;
  248. else    // Assume 'D'
  249.     folderType = kDesktopFolderType;
  250. if (FindFolder(kOnSystemDisk, folderType, kCreateFolder, &aliasVRefNum, &aliasDirID))
  251.     goto Fail;
  252.  
  253. // Delete alias if doing remove operation
  254. if (gParms->doingRemove)
  255.     {    // Delete alias
  256.     if (DeleteItem(aliasVRefNum, aliasDirID, gParms->itemName))
  257.         {    // Item could not be deleted
  258.         ParamText(gParms->itemName, gEmptyStr, gEmptyStr, gEmptyStr);
  259.         StopAlert(deleteAlrt, NULL);
  260.         gParms->result = siHookQuit;    // Force installer to quit
  261.         }
  262.     return;
  263.     }
  264.  
  265. // Create the alias file
  266. error = HDelete(aliasVRefNum, aliasDirID, gParms->itemName);
  267. if (error && (error != fnfErr))
  268.     goto Fail;
  269.  
  270. HCreateResFile(aliasVRefNum, aliasDirID, gParms->itemName);
  271. if (ResError())
  272.     goto Fail;
  273. fileCreated = true;
  274.  
  275. // Open the resource file and add an alias resource
  276. aliasResFileNum = HOpenResFile(aliasVRefNum, aliasDirID, gParms->itemName, fsRdWrPerm);
  277. if (aliasResFileNum == -1)
  278.     goto Fail;
  279. fileOpen = true;
  280.  
  281. if (FSMakeFSSpec(gParms->desVRefNum, gParms->desDirID, gParms->itemName, &targFSS))
  282.     goto Fail;
  283.  
  284. if (NewAlias(NULL, &targFSS, &aliasHdl))
  285.     goto Fail;
  286.  
  287. AddResource((Handle) aliasHdl, 'alis', 0, "\p");    // Create alias resource
  288. if (ResError())
  289.     goto Fail;
  290.  
  291. ChangedResource((Handle) aliasHdl);
  292. if (ResError())
  293.     goto Fail;
  294.  
  295. WriteResource((Handle) aliasHdl);
  296. if (ResError())
  297.     goto Fail;
  298.  
  299. fileOpen = false;
  300. CloseResFile(aliasResFileNum);
  301. if (ResError())
  302.     goto Fail;
  303.  
  304. // Determine the type and creator for the alias based on the type of target
  305. ib.dirInfo.ioVRefNum = gParms->desVRefNum;
  306. ib.dirInfo.ioDrDirID = gParms->desDirID;
  307. ib.dirInfo.ioNamePtr = gParms->itemName;
  308. ib.dirInfo.ioFVersNum = 0;
  309. ib.dirInfo.ioFDirIndex = 0;
  310. if (PBGetCatInfoSync(&ib))
  311.     goto Fail;
  312.  
  313. if (ib.hFileInfo.ioFlAttrib & ioDirMask)
  314.     {    // Item is a folder
  315.     aliasType = kContainerFolderAliasType;
  316.     aliasCreator = 'MACS';
  317.     }
  318. else
  319.     {    // Item is a file
  320.     aliasType = ib.hFileInfo.ioFlFndrInfo.fdType;
  321.     if (aliasType == 'APPL')
  322.         aliasType = kApplicationAliasType;    // Use special type for applications
  323.     aliasCreator = ib.hFileInfo.ioFlFndrInfo.fdCreator;
  324.     }
  325.  
  326. // Set the type and creator of the alias file and set the alias bit in the Finder flags
  327. if (HGetFInfo(aliasVRefNum, aliasDirID, gParms->itemName, &finderInfo))
  328.     goto Fail;
  329. finderInfo.fdType = aliasType;
  330. finderInfo.fdCreator = aliasCreator;
  331. finderInfo.fdFlags |= kIsAlias;
  332. if (HSetFInfo(aliasVRefNum, aliasDirID, gParms->itemName, &finderInfo))
  333.     goto Fail;
  334.  
  335. return;    // Good completion
  336.  
  337. // Error occurred during update
  338. Fail:
  339. gParms->result = siHookAbort;
  340.  
  341. if (fileOpen)
  342.     CloseResFile(aliasResFileNum);
  343. if (fileCreated)
  344.     HDelete(aliasVRefNum, aliasDirID, gParms->itemName);
  345. StopAlert(aliasAlrt, NULL);
  346. }
  347.  
  348.  
  349. /*****************************************************************************/
  350. OSErr DeleteItem(
  351.         short delVRefNum,    // Volume reference number of item to delete
  352.         long delDirID,        // Directory ID of item to delete
  353.         StringPtr delName    // Name of item to delete
  354.         )
  355. /******************************************************************************
  356.     Delete the specified file or folder. Return error code if any error occurs
  357.     (except "File Not Found") which prevents deleting the item.
  358. ******************************************************************************/
  359. {
  360. OSErr error;
  361. CInfoPBRec ib;
  362. long saveDirID;
  363. Str31 name;
  364. short trashVRefNum;
  365. long trashDirID;
  366.  
  367. ib.dirInfo.ioVRefNum = delVRefNum;
  368. ib.dirInfo.ioDrDirID = delDirID;
  369. ib.dirInfo.ioNamePtr = delName;
  370. ib.dirInfo.ioFVersNum = 0;
  371. ib.dirInfo.ioFDirIndex = 0;
  372. if (error = PBGetCatInfoSync(&ib))
  373.     {
  374.     if (error == fnfErr)
  375.         error = noErr;    // Item does not exist - return no error
  376.     goto Done;
  377.     }
  378.  
  379. if (ib.hFileInfo.ioFlAttrib & ioDirMask)
  380.     {    // Item is a folder - delete all items in folder first
  381.     saveDirID = ib.dirInfo.ioDrDirID;
  382.     ib.dirInfo.ioNamePtr = name;
  383.     ib.dirInfo.ioFDirIndex = 1;
  384.     for (;;)
  385.         {
  386.         ib.dirInfo.ioDrDirID = saveDirID;
  387.         ib.dirInfo.ioFVersNum = 0;
  388.         if (error = PBGetCatInfoSync(&ib))
  389.             {
  390.             if (error == fnfErr)
  391.                 break;    // End of directory
  392.             goto Done;
  393.             }
  394.         if (DeleteItem(delVRefNum, saveDirID, name))
  395.             ib.dirInfo.ioFDirIndex++;    // This delete failed - go to next item
  396.         }
  397.     error = HDelete(delVRefNum, delDirID, delName);    // Delete folder
  398.     }
  399. else
  400.     {    // Item is a file
  401.     if (error = HDelete(delVRefNum, delDirID, delName))
  402.         {    // Delete failed
  403.         // Try moving file to the trash instead of deleting it (note that this
  404.         // will not work for system software prior to 7.0)
  405.         // Find trash folder
  406.         if (FindFolder(delVRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID))
  407.             goto Done;    // Report error from file delete (this will fail if system software is pre-7.0)
  408.         if (trashVRefNum != delVRefNum)
  409.             goto Done;    // Can't move item to trash if not on the same volume
  410.         HDelete(trashVRefNum, trashDirID, delName);    // Delete possible duplicate in trash
  411.         if (CatMove(delVRefNum, delDirID, delName, trashDirID, "\p:"))
  412.             goto Done;    // Report error from file delete
  413.         error = noErr;    //    Report no error if file was successfully moved to trash
  414.         }
  415.     }
  416.  
  417. Done:
  418. return error;
  419. }
  420.